﻿using STHPMS1.Common.C_Entity;
using STHPMS1.Common.C_Entity.Stmpms1;
using STHPMS1.ICore;
using STHPMS1.ICore.I_DAL;
using STHPMS1.ICore.I_Entity.Info;
using STHPMS1.ICore.I_Entity.Stmpms1;
using STHPMS1.ICore.I_Serv;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using STHPMS1.Common.C_Extension;
using STHPMS1.Common.C_Enum;
using System.Linq.Expressions;
using System.Drawing;
using System.Data;
using EmitMapper;

namespace STHPMS1.BLL.B_Serv
{
    public class RoadDividedService : IRoadDividedService
    {
        private ISthpms1Dao _dao;
        private string _rdwayid;
        private double _version;
        private int _direction_Dictid;
        private bool _flag;
        private bool _isAll;

        private B_Roadway _road;
        private List<B_Rdstandard> _standardList;
        private List<B_Sturcture> _sturctureList;
        private List<B_Pmstc> _pmstcList;
        private List<B_Layer> _layerList;
        private Dictionary<double, string> _stakeList;
        private List<B_Invntory> _invntoryList;
        private List<B_Unit> _unitLit;
        private List<B_Invntory_Unit> _relList;
        private List<Dm_Modelgroup> _models;

        private List<B_History_Details> _consHistory;



        public void GenerateRoadSegAndUnit(ISthpms1Dao dao,string rdwayid, double version, int direction_Dictid,bool isAll=false)
        {
            try
            {
                _dao=dao;
                _rdwayid = rdwayid;
                _version = version;
                _direction_Dictid = direction_Dictid;
                _isAll = isAll;

                GetData(rdwayid, direction_Dictid);
                ExtractionStation();
                BuildData(rdwayid, version, direction_Dictid);     
            }
            catch (Exception err)
            {
                string msg = string.Format("[路线:{0},方向:{1}]-{2}",_road.Name,((DirectionEnum)direction_Dictid).GetEnumDescription(), err.Message);
                throw new Exception(msg);
            }
        }
        #region 保存数据 历史
        
        /// <summary>
        /// 保存数据 历史数据只保存变化的值 
        /// </summary>
        public void SaveData(RoadSaveService saveServ)
        {
            if (_direction_Dictid == DirectionEnum.All13.GetEnumValue())
            {
                saveServ.AllInvntoryList.AddRange(_invntoryList);
                saveServ.AllUnitList.AddRange(_unitLit);
                saveServ.AllRelList.AddRange(_relList);
            }
            else if (_direction_Dictid == DirectionEnum.Up11.GetEnumValue())
            {
                saveServ.UpInvntoryList.AddRange(_invntoryList);
                saveServ.UpUnitList.AddRange(_unitLit);
                saveServ.UpRelList.AddRange(_relList);
            }
            else if (_direction_Dictid == DirectionEnum.Down12.GetEnumValue())
            {
                saveServ.DownInvntoryList.AddRange(_invntoryList);
                saveServ.DownUnitList.AddRange(_unitLit);
                saveServ.DownRelList.AddRange(_relList);
            }

           
        }
        #endregion

        #region 生成路段单元数据
        /// <summary>
        /// 生成数据
        /// </summary>
        /// <param name="rdwayid"></param>
        /// <param name="direction_Dictid"></param>
        private void BuildData(string rdwayid, double version, int direction_Dictid)
        {
            List<double> stakeList = _stakeList.Keys.ToList();
            SortStakeList(stakeList);

            _invntoryList = GenerateSegList(stakeList, version, direction_Dictid);
            _unitLit = GenerateUnitList(stakeList, version, direction_Dictid);
            _relList = GenerateInvoeryAndUnit(version,_invntoryList, _unitLit);

        }

        private List<B_Invntory_Unit> GenerateInvoeryAndUnit(double version, List<B_Invntory> invntoryList, List<B_Unit> unitLit)
        {
            IKeyGenrateService service = MyApp.Locator.GetInstance<IKeyGenrateService>();
            List<B_Invntory_Unit> list = new List<B_Invntory_Unit>();
            foreach (B_Unit unit in unitLit)
	        {
		        B_Invntory invntory=invntoryList.FirstOrDefault(p=>unit.Beginmp>=p.Beginmp && unit.Endmp<=p.Endmp && unit.Direction_Dictid==p.Direction_Dictid);
                if(invntory==null)
                    throw new Exception(string.Format("[{0}]没有对应到路段",unit.Name));
                B_Invntory_Unit rel=new B_Invntory_Unit();
                rel.Relatedid=service.NewGuid();
                rel.Segid=invntory.Segid;
                rel.Unit=unit.Unit;
                rel.Rdwayid = unit.Rdwayid;
                rel.Direction_Dictid = unit.Direction_Dictid;
                rel.His_Version=version;
                list.Add(rel);
	        }
            return list;
        }

        /// <summary>
        /// 生成单元列表
        /// </summary>
        /// <param name="stakeList"></param>
        /// <param name="version"></param>
        /// <param name="direction_Dictid"></param>
        /// <returns></returns>
        private List<B_Unit> GenerateUnitList(List<double> stakeList, double version, int direction_Dictid)
        {
            IKeyGenrateService service = MyApp.Locator.GetInstance<IKeyGenrateService>();
            /**整桩号**/
            List<Section> segList=new List<Section>();
            int beginSeg=(int)Math.Floor(_road.Beginmp / 1000)*1000;
            while(true)
            {
                int endSeg= beginSeg+1000;
                segList.Add(new Section(){BeginMp=beginSeg,EndMp=endSeg});
                if(endSeg>=_road.Endmp)break;
                beginSeg=endSeg;

            }

            List<B_Unit> units = new List<B_Unit>();
            int i =1;
            foreach (var item in DividedStakes(stakeList, segList))
            {
                double beginmp = item.BeginMp;
                double endmp = item.EndMp;

                units.Add(CreateUnit(version, service, (int)direction_Dictid, i++, beginmp, endmp));
                              
            }
            return units;
        }

        public B_Unit CreateUnit(double version, IKeyGenrateService service, int direct, int num, double beginmp, double endmp)
        {
            B_Unit unit = new B_Unit();
            unit.Unit = service.NewUnitId(_road.Rdwayid, direct, beginmp, endmp);
            unit.Name = service.NewUnitName(_road.Name, direct,num);
            unit.Beginmp = beginmp;
            unit.Endmp = endmp;
            unit.Rdwayid = _road.Rdwayid;
            unit.Direction_Dictid = direct;
            unit.His_Version = version;
            return unit;
        }

        /// <summary>
        /// 划分桩号
        /// </summary>
        /// <param name="stakeList"></param>
        /// <param name="segList"></param>
        private List<Section> DividedStakes(List<double> stakeList, List<Section> segList)
        {
            List<Section> unitList = new List<Section>();
            int cur = 0;
            Section tmpStake = null;
            foreach (var seg in segList)
            {
             Found:
                if (cur >= stakeList.Count) break;
                double stake = stakeList[cur];

                if (stake > seg.BeginMp && stake < seg.EndMp)
                {
                    if (cur + 1 < stakeList.Count) //同一单元内可能同时存在两个桩号
                    {
                        double stake1 = stakeList[cur + 1];
                        if (stake1 > seg.BeginMp && stake1 < seg.EndMp)
                        {
                            if (tmpStake != null)
                            {
                                tmpStake.EndMp = stake;
                                unitList.Add(tmpStake);
                                tmpStake = null;
                            }
                            else
                                unitList[unitList.Count - 1].EndMp = stake;

                            unitList.Add(new Section() { BeginMp = stake, EndMp = stake1 });
                            tmpStake = new Section() { BeginMp = stake1, EndMp = seg.EndMp };

                            cur = cur + 2;
                            continue;
                        }
                    }
                    
                    Section leftStake = new Section() { BeginMp = seg.BeginMp, EndMp = stake };
                    Section rightStake = new Section() { BeginMp = stake, EndMp = seg.EndMp };


                    if (leftStake.Distance < 500)
                    {
                        if (tmpStake != null)
                        {
                            tmpStake.EndMp = leftStake.EndMp;
                            unitList.Add(tmpStake);
                            tmpStake = null;
                        }
                        else
                        {
                            if (unitList.Count > 0)
                                unitList[unitList.Count - 1].EndMp = leftStake.EndMp;                        
                        }
                    }                        
                    else
                    {
                        if (leftStake.BeginMp > _road.Beginmp)
                        {
                            if (tmpStake != null)
                            {
                                tmpStake.EndMp = leftStake.EndMp;
                                unitList.Add(tmpStake);
                                tmpStake = null;
                            }
                            else
                                unitList.Add(leftStake);
                        }
                    }

                    if (leftStake.EndMp == _road.Endmp)
                    {
                        if (unitList[unitList.Count - 1].Distance < 500)
                        {
                            Section fail = unitList[unitList.Count - 1];
                            unitList.Remove(fail);
                            unitList[unitList.Count - 1].EndMp = fail.EndMp;
                        }
                        break;
                    }

                    if (rightStake.Distance < 500)
                        tmpStake = rightStake;
                    else
                        unitList.Add(rightStake);
                    cur++;
                }
                else
                {
                    if (cur + 1 < stakeList.Count) //同一单元内可能同时存在两个桩号
                    {
                        double stake1 = stakeList[cur + 1];
                        if (stake1 > seg.BeginMp && stake1 < seg.EndMp)
                        {
                            cur = cur + 1;
                            goto Found;
                        }
                    }
                    

                    if (tmpStake != null)
                    {
                        tmpStake.EndMp = seg.EndMp;
                        unitList.Add(tmpStake);
                        tmpStake = null;
                    }
                    else
                        unitList.Add(seg);

                    if (seg.EndMp == _road.Endmp) break;
                    if (stake == seg.BeginMp || stake == seg.EndMp) cur++;
                }
            }

            return unitList;
        }

        /// <summary>
        /// 生成路段列表
        /// </summary>
        /// <param name="stakeList"></param>
        /// <param name="version"></param>
        /// <param name="direction_Dictid"></param>
        /// <returns></returns>
        private List<B_Invntory> GenerateSegList(List<double> stakeList, double version, int direction_Dictid)
        {
            List<B_Invntory> invntoryList = new List<B_Invntory>();
            IKeyGenrateService service = MyApp.Locator.GetInstance<IKeyGenrateService>();

            for (int i = 1; i < stakeList.Count; i++)
            {
                double beginmp = stakeList[i - 1];
                double endmp = stakeList[i];
                if ((endmp-beginmp)<500)
                {
                    throw new Exception(string.Format("{0}:{1}-{2}:{3} 桩号之间的距离小于500", _stakeList[beginmp], beginmp.PrintStake(), _stakeList[endmp], endmp.PrintStake()));
                }
                    
                invntoryList.Add(CreateInvntory(version, service, (int)direction_Dictid, i, beginmp, endmp));
            }

            return invntoryList;
        }

        private B_Invntory CreateInvntory(double version, IKeyGenrateService service, int direct, int num, double beginmp, double endmp)
        {
            B_Invntory invntory = new B_Invntory();
            invntory.Segid = service.NewInvntoryId(_road.Rdwayid, direct, beginmp, endmp);
            invntory.Name = service.NewInvntoryName(_road.Name, direct, num);
            invntory.Rdwayid = _road.Rdwayid;
            invntory.Beginmp = beginmp;
            invntory.Endmp = endmp;
            invntory.Direction_Dictid = direct;
            invntory.Admdiv = int.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R202, invntory.Beginmp, direct));
            invntory.Manaut = GetRdValue(_standardList, RdStandardTypeEnum.R203, invntory.Beginmp, direct);
            B_Pmstc pmstc = _pmstcList.FirstOrDefault(p => invntory.Beginmp >= p.Beginmp && invntory.Endmp <= p.Endmp);
            if (pmstc == null) throw new Exception(string.Format("路段[{0}-{1}]之间的面层类型没有找到", invntory.Beginmp.PrintStake(), invntory.Endmp.PrintStake()));
            invntory.Pvmttype_Dictid = pmstc.Pvmttype_Dictid;
            invntory.Basictype_Dictid = pmstc.Basictype_Dictid;
            invntory.Numlanes = int.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R204, invntory.Beginmp, direct));
            invntory.Surfwidth = double.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R205, invntory.Beginmp, direct));
            invntory.Sltp_Dictid = int.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R206, invntory.Beginmp, direct));
            invntory.Should_Dictid = int.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R208, invntory.Beginmp, direct));
            invntory.Admgrd = _road.Admgrd;
            invntory.Rdclass_Dictid = int.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R210, invntory.Beginmp, direct));
            var year=int.Parse(GetRdValue(_standardList, RdStandardTypeEnum.R209, invntory.Beginmp, direct));
            invntory.Begindate = new DateTime(year, 1, 1);

            MainTypeEnum mainType = MainTypeEnum.M12003;
            string model_groupid = null;
            if(_road.His_Version!=null)
            {
                B_History_Details hisotry=_consHistory.FirstOrDefault(p => (invntory.Beginmp >= p.Beginmp && invntory.Endmp <= p.Endmp) && invntory.Direction_Dictid == p.Direction_Dictid);
                if (hisotry != null)
                {
                    if (hisotry.Pave_Type == MainTypeEnum.M12003.GetEnumValue())
                    {
                        invntory.Begindate = new DateTime(hisotry.Year, 1, 1);
                    }
                    else if (hisotry.Pave_Type == MainTypeEnum.M12002.GetEnumValue())
                    {
                        mainType = MainTypeEnum.M12002;
                    }
                    else if (hisotry.Pave_Type == MainTypeEnum.M12001.GetEnumValue())
                    {
                        mainType = MainTypeEnum.M12001;
                        B_Layer layer=_layerList.FirstOrDefault(p => p.Struid == pmstc.Struid && p.Layer_Dictid == LayerEnum.L30.GetEnumValue());
                        if (layer == null) throw new Exception("预养护后路面结构的上面层数据为空，没有养护措施，无法进行模型匹配-"+pmstc.Struid);
                        ///TODO:修改模型组ID的规则
                        model_groupid = layer.Stru_Id;
                    }
                }
            }


            Dm_Modelgroup pci = null;
            if (model_groupid == null)
                pci = _models.FirstOrDefault(p => p.Pvmttype_Dictid == pmstc.Pvmttype_Dictid &&
                                            p.Basictype_Dictid == pmstc.Basictype_Dictid &&
                                            p.Modeltype_Dictid == mainType.GetEnumValue() &&
                                            (pmstc.Thick_S >= p.Thick_Min && pmstc.Thick_S <= p.Thick_Max));
            else
                pci = _models.FirstOrDefault(p => p.Pvmttype_Dictid == pmstc.Pvmttype_Dictid &&
                                            p.Basictype_Dictid == pmstc.Basictype_Dictid &&
                                            p.Modeltype_Dictid == mainType.GetEnumValue() &&
                                            p.Comment==model_groupid &&
                                            (pmstc.Thick_S >= p.Thick_Min && pmstc.Thick_S <= p.Thick_Max));

            if (pci == null)
                throw new Exception(string.Format("PCI 模型没有找到-{0}_{1}_{2}", ((PavementTypeEnum)pmstc.Pvmttype_Dictid).GetEnumDescription(), ((RoadBasicTypeEnum)pmstc.Basictype_Dictid).GetEnumDescription(), pmstc.Thick_S));
            invntory.Modelgroup_Pci = pci.Modelgroup_Id;
          
            invntory.Importdate = DateTime.Now;
            invntory.His_Version = version;
            return invntory;
        }

        private string GetRdValue(List<B_Rdstandard> standardList, RdStandardTypeEnum type, double stake, int direct)
        {
            DirectionEnum direction=(DirectionEnum)direct;
            var list =standardList.Where(p => p.Changetype_Dictid == type.GetEnumValue()).ToArray();
            if (list.Count() == 0)
                throw new Exception(string.Format("没有找到标准{0}中对应的值", type.GetEnumDescription()));
            int index=-2;
            for (int i = 0; i < list.Count(); i++)
            {
                if (stake == list[i].Beginmp)
                {
                    index = i;
                    break;
                }
                else if (stake < list[i].Beginmp)
                {
                    index = i-1;
                    break;
                }
            }
            if (index == -1) index = 0;
            if (index == -2) index = list.Length - 1;

            return list[index].Value;
        }

        #endregion

        #region 提取桩号
        /// <summary>
        /// 提取桩号
        /// </summary>
        private void ExtractionStation()
        {
            _stakeList =  new Dictionary<double, string>();
            ExtractionRdStandardStation(_stakeList);
            ExtractionStructureListStation(_stakeList);
            ExtractionPmstcStation(_stakeList);
        }
        /// <summary>
        /// 排序桩号
        /// </summary>
        private void SortStakeList(List<double> stakeList)
        {
            stakeList.Sort();
        }
        /// <summary>
        /// 提取路面结构桩号
        /// </summary>
        /// <param name="stakeList"></param>
        private void ExtractionPmstcStation(Dictionary<double, string> stakeList)
        {
            double stake = _road.Beginmp;
            foreach (var pmstc in _pmstcList)
            {
                if (pmstc.Beginmp < _road.Beginmp) throw new Exception(string.Format("路面结构：起点桩号：{0},小于路线的起点桩号", pmstc.Beginmp.PrintStake()));
                if (pmstc.Endmp > _road.Endmp) throw new Exception(string.Format("路面结构：终点桩号：{0},大于路线的终点桩号", pmstc.Endmp.PrintStake()));
                if (pmstc.Beginmp > pmstc.Endmp) throw new Exception(string.Format("路面结构：起点桩号大于终点桩号"));
                if (pmstc.Beginmp != stake) throw new Exception(string.Format("路面结构：{0}-{1}段路面结构不存在", stake, pmstc.Beginmp.PrintStake()));
                if (pmstc.Thick_T == null || pmstc.Thick_T == 0) throw new Exception(string.Format("路面结构：{0}段路面结构总厚度不能为空或者0", pmstc.Beginmp.PrintStake()));
                if (pmstc.Thick_S == null || pmstc.Thick_S == 0) throw new Exception(string.Format("路面结构：{0}段路面结构面层厚度不能为空或者0", pmstc.Beginmp.PrintStake()));

                AddStake(stakeList, pmstc.Beginmp, RdStandardTypeEnum.R200);

                AddStake(stakeList, pmstc.Endmp, RdStandardTypeEnum.R200);

                stake = pmstc.Endmp;
            }
            if (_road.Endmp != stake) throw new Exception(string.Format("路面结构：{0}-{1}段路面结构不存在", stake.PrintStake(), _road.Endmp.PrintStake()));             
        }
        /// <summary>
        /// 提取构造物桩号
        /// </summary>
        /// <param name="stakeList"></param>
        private void ExtractionStructureListStation(Dictionary<double, string> stakeList)
        {
            B_Sturcture last = null;
            foreach (var structure in _sturctureList)
            {
                string struname = structure.Struname;

                if (structure.Beginmp < _road.Beginmp) throw new Exception(string.Format("构造物：{0}-起点桩号：{1},小于路线的起点桩号", struname, structure.Beginmp.PrintStake()));
                if (structure.Endmp > _road.Endmp) throw new Exception(string.Format("构造物：{0}-终点桩号：{1},大于路线的终点桩号", struname, structure.Endmp.PrintStake()));
                if (structure.Beginmp > structure.Endmp) throw new Exception(string.Format("构造物：{0}-起点桩号大于终点桩号", struname));
                if ((structure.Endmp - structure.Beginmp) < 500) continue;//小于500米的桥遂构造物不参与分段
                if (structure.Sttype_Dictid == SturctureEnum.C125.GetEnumValue()) continue;//涵洞不参与分段
                if (last != null)
                {
                    if (structure.Beginmp < last.Endmp)
                        throw new Exception(string.Format("构造物：{0}-{1} 桩号有重叠", struname, last.Struname));
                }

                AddStake(stakeList, structure.Beginmp, RdStandardTypeEnum.R201);

                AddStake(stakeList, structure.Endmp, RdStandardTypeEnum.R201);

                last = structure;
            }
        }
        /// <summary>
        /// 提取路段标准桩号
        /// </summary>
        /// <param name="stakeList"></param>
        private void ExtractionRdStandardStation(Dictionary<double, string> stakeList)
        {
            foreach (var standard in _standardList)
            {
                RdStandardTypeEnum standardType = (RdStandardTypeEnum)standard.Changetype_Dictid;
                if (standard.Beginmp==null) throw new Exception(string.Format("划分标准：{0}-桩号是空的", standardType.GetEnumDescription()));               
                double stake=(double)standard.Beginmp;
                if (stake < _road.Beginmp) throw new Exception(string.Format("划分标准：{0}-桩号：{1},小于路线的起点桩号", standardType.GetEnumDescription(), stake.PrintStake()));
                if (stake > _road.Endmp) throw new Exception(string.Format("划分标准：{0}-桩号：{1},大于路线的终点桩号", standardType.GetEnumDescription(), stake.PrintStake()));
                if (standardType != RdStandardTypeEnum.R207 && string.IsNullOrEmpty(standard.Value))
                    throw new Exception(string.Format("划分标准：{0}-桩号：{1} 其值不能为空", standardType.GetEnumDescription(), stake.PrintStake()));

                AddStake(stakeList, stake, standardType);
            }
        }

        /// <summary>
        /// 将桩号添加到集合中
        /// </summary>
        /// <param name="stakeList"></param>
        /// <param name="stake"></param>
        private void AddStake(Dictionary<double,string> stakeList,double stake,RdStandardTypeEnum type)
        {
            string desc=type.GetEnumDescription();
            if (stake == _road.Beginmp) desc = "起点桩号";
            if (stake == _road.Endmp) desc = "终点桩号";

            if (!stakeList.ContainsKey(stake))
            {
                stakeList.Add(stake, desc);
            }
            else {
                stakeList[stake] += "," + desc;
            }
        }        
        #endregion


        #region 获取数据
        /// <summary>
        /// 从服务器提取数据
        /// </summary>
        /// <param name="rdwayid"></param>
        /// <param name="direction_Dictid"></param>
        private void GetData(string rdwayid, int direction_Dictid)
        {
            if (_dao == null) throw new Exception("数据库操作对象为空!");
            _road = _dao.Single<B_Roadway>(p=>p.Rdwayid==rdwayid);
            _models = _dao.Select<Dm_Modelgroup>();
            _standardList = _dao.Select<B_Rdstandard>(p => p.Rdwayid == rdwayid , new DefPageInfo(), k => k.Beginmp);
            if (_isAll)
            {
                _sturctureList = _dao.Select<B_Sturcture>(p => p.Rdwayid == rdwayid && ( p.Direction_Dictid == direction_Dictid || p.Direction_Dictid==DirectionEnum.All13.GetEnumValue()), new DefPageInfo(), k => k.Beginmp);
                _pmstcList = _dao.Select<B_Pmstc>(p => p.Rdwayid == rdwayid && (p.Direction_Dictid == direction_Dictid || p.Direction_Dictid == DirectionEnum.All13.GetEnumValue()), new DefPageInfo(), k => k.Beginmp);
                _layerList = _dao.Select<B_Layer>(p => p.Rdwayid == rdwayid && ( p.Direction_Dictid == direction_Dictid || p.Direction_Dictid==DirectionEnum.All13.GetEnumValue()));
     
            }
            else
            {
                _sturctureList = _dao.Select<B_Sturcture>(p => p.Rdwayid == rdwayid && p.Direction_Dictid == direction_Dictid, new DefPageInfo(), k => k.Beginmp);
                _pmstcList = _dao.Select<B_Pmstc>(p => p.Rdwayid == rdwayid && p.Direction_Dictid == direction_Dictid, new DefPageInfo(), k => k.Beginmp);
                _layerList = _dao.Select<B_Layer>(p => p.Rdwayid == rdwayid && p.Direction_Dictid == direction_Dictid);
            }
            _consHistory = _dao.Select<B_History_Details>(p => p.Rdwayid == rdwayid && p.His_Version == (_road.His_Version??0));

            
        }
       
        #endregion

        public void Dispose()
        {
            _dao=null;
            _road=null;
            _models = null;
            _stakeList=null;
            _sturctureList=null;
            _pmstcList=null;
            _layerList=null;
            _stakeList=null;
            _invntoryList=null;
            _unitLit=null;
            _relList=null;
        }


        class Section
        {
            public double BeginMp;
            public double EndMp;
            public double Distance
            {
                get{
                    return EndMp - BeginMp;
                }                
            }
        }

    }
}
